package ig.finanzas;

import ig.finanzas.riesgo.FactorRiesgoPersonal;
import ig.metrica.escenario.GeneraEscenarioBean;
import ig.util.ejb.IGBean;
import ig.util.excepciones.DatoInvalidoExcepcion;
import ig.util.excepciones.LogicaExcepcion;
//import java.io.FileNotFoundException;
import java.rmi.RemoteException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 *
 * Implementa los metodos y funciones de un contrato que no puede ser atomizable
 * o desmaterializable.
 *
 * Para este tipo de contrato no se manejan valores registrados.
 *
 * @author lfgarcia
 *
 */
public class ContratoSimpleBean extends ContratoBean {

    static final long serialVersionUID = 01;
    private String nombre;
    private String tipo;

    
    /**
     *
     * Devuelve el nombre del contrato.
     *
     * @return
     *
     * @uml.property name="nombre"
     *
     */
    public String getNombre() {

        return nombre;

    }

    /**
     *
     * Devuelve el tipo de contrato. Los valores validos son Disponible para la
     * Venta y negociables.
     *
     * @return
     *
     * @uml.property name="tipo"
     *
     */
    public String getTipo() {

        return tipo;

    }

    /**
     *
     * @param tipo The tipo to set.
     *
     * @uml.property name="tipo"
     *
     */
    public void setTipo(String tipo) throws DatoInvalidoExcepcion, Exception {
        if (!tipo.equals(ContratoSimple.TIPO_DISPONIBLEVENTA) && !tipo.equals(ContratoSimple.TIPO_NEGOCIABLE)) {
            throw new DatoInvalidoExcepcion("El tipo especificado para la posicion " + pk.getIdInterna() + " no es valido");
        }
        this.tipo = tipo;
    }

    /**
     *
     * Calcula el valor en riesgo del contrato.
     *
     * @param fecha
     *
     * @param numdias Este parametro solo se utiliza cuando como tasa de
     * referencia se utiliza la curva cero cupon
     *
     * exclusivamente para el calculo de la volatilidad de la misma.
     *
     * @param factor
     *
     * @return
     *
     * @throws DatoInvalidoExcepcion Si la fecha o el factor especificado son
     * nulos, o si el factor de riesgo definido no es de tipo tasa, o si el valor 
     * de la tasa en esa fecha es menor o igual a -1.
     *
     * @throws LogicaExcepcion Si el contrato no tiene flujos,
     * o si no se puede determinar el valor de la tasa en dicha fecha.
     * @throws FinderException Si no se puede cargar la tasa de descuento.
     *
     */
    public double valorEnRiesgo(Date fecha, int numdias, FactorRiesgoPersonal factor)
            throws DatoInvalidoExcepcion, LogicaExcepcion, Exception {

        //VER = ValorDeMercado * duracion / (1+TIR) * cambioesperado

        if (fecha == null) {
            throw new DatoInvalidoExcepcion("La fecha especificada es nula.");
        }

        if (factor == null) {
            throw new DatoInvalidoExcepcion("El factor de riesgo especificado es nulo.");
        }

        if (factor.getTipo() != FactorRiesgoPersonal.TIPO_FACTORTASA) {
            throw new DatoInvalidoExcepcion("El factor de riesgo especificado debe ser del tipo tasa.");
        }

        ManejadorFlujos flujosduracion = flujosParaDuracion(fecha);
        TasaBean tasa = getTasa(factor.getTasaPK());
        
        double valorDeMercado = flujosduracion.valorDescontado(tasa, fecha, 0.0);
        double duracion = flujosduracion.duracion(fecha, tasa);
        double tir = flujosduracion.tir();
        double cambioesperado = 0;

        if (factor.getTipoCalculoCambioEsperado() == FactorRiesgoPersonal.CAMBIOESPERADO_FACTORMATRIZ) {
            cambioesperado = factor.getFactorRiesgoMatrizCorrelacion().getCambioEsperado();
        } else {
            try {
                cambioesperado = tasa.cambioEsperadoValoresRegistrados(fecha, factor.getDefinidorCalculoCambioEsperado());
            } catch (Exception e) {}
        }


        double ver = valorDeMercado * duracion / (1 + tir) * cambioesperado;
        return ver;
    }

    public void eliminarEntidad() {
    }

    public void actualizarEntidad() {
    }

    public void cargarEntidad() throws DatoInvalidoExcepcion, SQLException, Exception {
        Statement st = null;
        ResultSet r1 = null;
        try {
            Long idInterna = pk.getIdInterna();
            conn = IGBean.getMetricaDB();//getConexion("METRICADB");
            st = conn.createStatement();
            String txtsql = "SELECT C.NOMBRE AS CONTRATO, C.TIPO AS TIPO, M.NOMBRE AS MONEDA, M.ID AS IDMONEDA  "
                    + "FROM CONTRATOSSIMPLES C, PRODUCTOS P, MONEDAS M, CONTRATOS C2  "
                    + "WHERE C2.IDPRODUCTO=P.ID AND P.IDMONEDA=M.ID AND C.ID=C2.ID AND C.ID='" + idInterna + "'";

            r1 = st.executeQuery(txtsql);
            r1.next();
            //Carga de los atributos especificos
            this.nombre = r1.getString("CONTRATO");
            setTipo(r1.getString("TIPO"));
            //Carga de los atributos generales
            this.monedaPK = new MonedaPK(r1.getString("MONEDA"));
            this.monedaPK.setIdInterna(r1.getLong("IDMONEDA"));
            cargarProductoPK(idInterna);
            cargarFlujos(idInterna);
            cargarTasasDePago(idInterna);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
//            try {
//                conn.close();
//            } catch (Exception e) {
//            }
            try {
                st.close();
            } catch (Exception e) {
            }
            try {
                r1.close();
            } catch (Exception e) {
            }
        }
    }

    public ContratoPK ejbFindByPrimaryKey(ContratoPK pk) throws Exception {
        ResultSet r1 = null;
        try {
            conn = IGBean.getMetricaDB();//getConexion("METRICADB");
            pstmt1 = conn.prepareStatement(
                    "SELECT ID "
                    + "FROM CONTRATOSSIMPLES "
                    + "WHERE ID=?");
            pstmt1.setLong(1, pk.getIdInterna());
            r1 = pstmt1.executeQuery();
            if (r1.next() == false) {
                throw new Exception("No fue posible encontrar el contrato simple " + pk.toString());
            }

            return pk;
        } catch (Exception e) {
            throw new Exception("No fue posible cargar el contrato simple " + pk.toString());
        } finally {
            try {
                pstmt1.close();
            } catch (SQLException e) {
            }
//            try {
//                conn.close();
//            } catch (SQLException e) {
//            }
            try {
                r1.close();
            } catch (SQLException e) {
            }
        }
    }

    public List ejbFindAll() throws Exception {
        ArrayList contratos = new ArrayList();
        ResultSet rs = null;
        try {
            conn = IGBean.getMetricaDB();//getConexion("METRICADB");
            pstmt1 = conn.prepareStatement("SELECT NOMBRE,TIPO,ID FROM CONTRATOSSIMPLES ");
            rs = pstmt1.executeQuery();
            while (rs.next()) {
                ContratoSimpleBean contratoSimpleBean = new ContratoSimpleBean();
                contratoSimpleBean.nombre = rs.getString("NOMBRE");
                contratoSimpleBean.tipo = rs.getString("TIPO");
                contratoSimpleBean.setPk(new ContratoPK(-1L));
                contratoSimpleBean.getPk().setIdInterna(rs.getLong("ID"));
                contratoSimpleBean.cargarEntidad();
                contratos.add( contratoSimpleBean );
            }
        } catch (Exception e) {
            throw new Exception(e.toString());
        } finally {
            try {
                pstmt1.close();
            } catch (SQLException e) {
            }
//            try {
//                conn.close();
//            } catch (SQLException e) {
//            }
            try {
                rs.close();
            } catch (SQLException e) {
            }
        }
        return contratos;
    }
}
